package com.xuecheng.framework.exception;

import com.google.common.collect.ImmutableMap;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;


/**
 * 统一异常处理类
 */
@ControllerAdvice//控制器增强
public class ExceptionCatch {
    private  static  final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);


    //定义一个Map，配置异常类型所对应的错误代码,
    //使用EXCEPTIONS存放异常类型和错误代码的映射，ImmutableMap的特点的一旦创建不可改变，并且线程安全
    private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;
    //使用builder来构建一个异常类型和错误代码的异常
    protected  static  ImmutableMap.Builder<Class<? extends  Throwable>,ResultCode> builder = ImmutableMap.builder();
    static {
        //定义异常类型所对应的错误代码
        builder.put(HttpMessageNotReadableException.class,CommonCode.INVALID_PARAM);
        //......需要时再去定义
    }



    //这里主要是捕获未知的异常
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public ResponseResult exception(Exception exception){
        LOGGER.error("catch exceprion:{}",exception.getMessage());
        if (EXCEPTIONS == null){
            EXCEPTIONS=builder.build();//EXCEPTIONS构建成功
        }
        //从EXCEPTIONS中找异常类型所对应的错误代码，如果找到了直接返回ImmutableMap中定义的Code值，没有返回999999异常
        ResultCode resultCode=EXCEPTIONS.get(exception.getClass());
        if(resultCode!=null){
            return  new ResponseResult(resultCode);
        }

        return  new ResponseResult(CommonCode.SERVER_ERROR);
    }


    //这里主要是捕获自定义的异常
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult customException(CustomException e) {
        LOGGER.error("catch exception : {}\r\nexception: ",e.getMessage(), e);
        ResultCode resultCode = e.getResultCode();
        ResponseResult responseResult = new ResponseResult(resultCode);
        return responseResult;
    }

}
